using Digitalmes.Domain.Entities.Mes.Productions;

namespace Digitalmes.Application.Services.Impl;

/// <summary>
/// 工单服务。
/// </summary>
/// <param name="workOrderRepo"></param>
/// <param name="sysConfigQueryService"></param>
internal sealed class WorkOrderService(IRepository<ProdWorkOrder> workOrderRepo,
    ISysConfigQueryService sysConfigQueryService) : IWorkOrderService
{
    public async Task<string?> GetWoAndIncrementStartedQtyAsync(long productId, CancellationToken cancellationToken = default)
    {
        var allowAutoCompleted = await IsAllowAutoCompleted();
        WoStatusEnum[] woStatus = [WoStatusEnum.Scheduled, WoStatusEnum.InProgress];

        // 按优先级找到第一个处于 "已排产" 或 "进行中" 的工单，若自动切换工单，找到（投产数量小于计划生产数量）；
        // 若是自动切换工单，只能比较投产数量与计划数量，因为无法判断线体上的在制品后续的下线状态。
        var workorder = await workOrderRepo.AsQueryable()
            .Where(m => m.ProductId == productId && woStatus.Contains(m.Status))
            .WhereIF(allowAutoCompleted, m => m.StartedQty < m.PlanQty) // 自动切换工单
            .OrderBy(m => m.Priority)
            .FirstOrDefaultAsync(cancellationToken);
        if (workorder is null)
        {
            return null;
        }

        workorder.StartedQty += 1; // 工单投产数量+1
        if (workorder.Status is WoStatusEnum.Scheduled)
        {
            workorder.ChangeStatus(WoStatusEnum.InProgress);
            workorder.ActualStartDate = DateTime.Now;
            await workOrderRepo.UpdateAsync(workorder, m => new
            {
                m.StartedQty,
                m.Status,
                m.LastStatus,
                m.ActualStartDate,
            }, cancellationToken);
        }
        else
        {
            await workOrderRepo.UpdateAsync(workorder, m => new
            {
                m.StartedQty,
            }, cancellationToken);
        }

        return workorder.Wo;
    }

    public async Task<bool> IncrementGoodQtyAsync(string wo, CancellationToken cancellationToken = default)
    {
        var workOrder = await workOrderRepo.FirstOrDefaultAsync(m => m.Wo == wo, cancellationToken);
        if (workOrder == null)
        {
            return false;
        }

        workOrder.GoodQty += 1;

        // 检查配置中是否有设置自动完工
        bool allowAutoCompleted = await IsAllowAutoCompleted();
        bool isAutoCompletedOnlyGoodQty = await IsAutoCompletedWhenMeetGoodQty();
        var actualQty = workOrder.GoodQty + (isAutoCompletedOnlyGoodQty ? 0 : workOrder.ScrappedQty);
        if (allowAutoCompleted && workOrder.PlanQty == actualQty)
        {
            workOrder.Complete();
            await workOrderRepo.UpdateAsync(workOrder, m => new
            {
                m.Priority,
                m.GoodQty,
                m.LastStatus,
                m.Status,
                m.ActualEndDate,
            }, cancellationToken);

            return true;
        }

        await workOrderRepo.UpdateAsync(workOrder, m => new
        {
            m.GoodQty,
        }, cancellationToken);

        return false;
    }

    public async Task<bool> IncrementScrapQtyAsync(string wo, CancellationToken cancellationToken = default)
    {
        var workOrder = await workOrderRepo.FirstOrDefaultAsync(m => m.Wo == wo, cancellationToken);
        if (workOrder == null)
        {
            return false;
        }

        workOrder.ScrappedQty += 1;
        // 检查配置中是否有设置自动完工
        bool allowAutoCompleted = await IsAllowAutoCompleted();
        bool isAutoCompletedOnlyGoodQty = await IsAutoCompletedWhenMeetGoodQty();
        var actualQty = workOrder.GoodQty + (isAutoCompletedOnlyGoodQty ? 0 : workOrder.ScrappedQty);
        if (allowAutoCompleted && workOrder.PlanQty == actualQty)
        {
            workOrder.Complete();
            await workOrderRepo.UpdateAsync(workOrder, m => new
            {
                m.Priority,
                m.ScrappedQty,
                m.LastStatus,
                m.Status,
                m.ActualEndDate,
            }, cancellationToken);

            return true;
        }

        await workOrderRepo.UpdateAsync(workOrder, m => new
        {
            m.ScrappedQty,
        }, cancellationToken);

        return false;
    }

    /// <summary>
    /// 工单是否允许自动完工。
    /// </summary>
    private async Task<bool> IsAllowAutoCompleted()
        => await sysConfigQueryService.IsYes(ConfigKeys.AllowWorkorderAutoCompleted);

    /// <summary>
    /// 工单单自动完工时，是否只在实际良品数量等于计划数量时才算完工。
    /// </summary>
    private async Task<bool> IsAutoCompletedWhenMeetGoodQty()
        => await sysConfigQueryService.IsYes(ConfigKeys.AllowWorkorderAutoCompletedWhenMeetGoodQty);
}
